package com.lsht.common.word;


import com.lsht.common.utils.StringUtils;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.xmlbeans.XmlException;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STThemeColor;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author zyc
 * @ClassName: WordCoverFied
 * @Description: 模板通配符全局替换工具-》》》请尊重劳动成果。 目前代码未优化
 * @date 2023/10/12  10/30
 */
@SuppressWarnings("all")
public class WordCoverFied {

    /**
     * 用一个docx文档作为模板，然后替换其中的内容，再写入目标文档中。
     *
     * @throws Exception
     */
//    @Test
//    public void templateWrite() throws Exception {
//        //替换段落里面的变量
//        replaceInPara(AsposeWordUtil.docToDocx("F:/HTHT/Mapping/models/model_not_day_report.doc"));
////        replaceInPara(  AsposeWordUtil.docToDocx("D:/modeldoc/model_wmy_report.doc") );
//
//        // replaceInPara(AsposeWordUtil.docToDocx("D:/HTHT/zhangqi/2022年石家庄市空气质量遥感监控周报-第28(20220704-20220710)周.docx" ), AsposeWordUtil.docToDocx("D:/modeldoc/model_wmy_report.doc") );
////        List H = new ArrayList<>();
////        String temp[] = new String[3];
////        temp[0] = "12131231";
////        temp[1] = "1213123sad1";
////        temp[2] = "121312211123sad1";
////        H.add(temp);
////        H.stream().forEach( v->{
////            List<String> H2 = new ArrayList<>();
////            Arrays.stream( (String[]) v ).forEach( vs->{
////                H2.add( vs );
////            } );
////            System.out.println(H2.get( 0 ));
////        } );
//    }

    /**
     * 替换段落里面的变量
     *
     * @param doc 要替换的文档
     */
    public static void replaceInPara(String filePath) throws IOException {
        InputStream iss = Files.newInputStream(Paths.get(filePath));
        XWPFDocument doc = new XWPFDocument(iss);
        AtomicInteger n = new AtomicInteger();
        System.out.println("|==========================|>模板通配符开始替换<|=======================================\n\t");
        doc.getParagraphs().stream().filter(Objects::nonNull).forEach(v -> {
            try {
                replaceInPara(v, n.getAndIncrement());
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });
        OutputStream oss = Files.newOutputStream(Paths.get(filePath));
        doc.write(oss);
        oss.close();
        iss.close();
        System.out.println("|==========================|>模板通配符结束替换<|=======================================\n\t");
    }

    /**
     * 替换段落里面的变量
     *
     * @param para 要替换的段落
     */
    private static synchronized void replaceInPara(XWPFParagraph para, int andIncrement) {
        List<XWPFRun> runs;
        Pattern pattern = Pattern.compile("#(.+?)#");
        Matcher matcher = pattern.matcher(para.getParagraphText());
        System.out.println("|开始替换 =\t" + para.getParagraphText() + "\t");
        runs = para.getRuns();
        while (matcher.find()) {
            String re = matcher.group().replace("#", "");
            String text = "";
            for (int i = 0; i < runs.size(); i++) {
                XWPFRun run = runs.get(i);
                //获取格式
                String runText = run.toString(), fam = run.getFontFamily(), color = run.getColor(), und = run.getUnderlineColor(), la = run.getLang(), pic = run.getPictureText();
                int size = run.getFontSize(), cha = run.getCharacterSpacing(), k = run.getKerning(), t = run.getTextPosition(), tx = run.getTextScale();
                boolean bold = run.isBold();
                UnderlinePatterns un = run.getUnderline();
                STThemeColor.Enum enums = run.getUnderlineThemeColor();
                String fama = "", colora = "", unda = "", laa = "";
                int sizea = 0;
                int chaa = 0;
                int ka = 0;
                int ta = 0;
                int txa = 0;
                VerticalAlign sb = (run.getSubscript());
                boolean bolda = false;
                UnderlinePatterns una = null;
                STThemeColor.Enum enumsa = null;
                VerticalAlign sba = null;
                XWPFRun runa;
                if (i > 0) {
                    runa = runs.get(i - 1);
                    //获取格式
                    fama = runa.getFontFamily();
                    colora = runa.getColor();
                    unda = runa.getUnderlineColor();
                    laa = runa.getLang();
                    sizea = runa.getFontSize();
                    chaa = runa.getCharacterSpacing();
                    ka = runa.getKerning();
                    ta = runa.getTextPosition();
                    txa = runa.getTextScale();
                    bolda = runa.isBold();
                    una = runa.getUnderline();
                    enumsa = runa.getUnderlineThemeColor();
                    sba = (run.getSubscript());
                }
                k = ka = 10;
                if (andIncrement == 0) {
                    fama = fam = "方正小标宋简体";
                    tx = txa = 90;
                } else {
                    ta = t = 0;
                    if (una != null && una.getValue() != 18) {
                        fama = fam = "楷体";
                    }
                }

                //特殊情况
                if (runs.size() > 3 && i > 2 && StringUtils.isNotEmpty(text) && StringUtils.isNotEmpty(runText)) {
                    XWPFRun runb = runs.get(i - 2);
                    int a = runb.getFontSize();
                    String b = runb.getFontFamily();
                    boolean c = runb.isBold();
                    String d = runb.getColor();
                    String e = runb.getUnderlineColor();
                    UnderlinePatterns f = runb.getUnderline();
                    STThemeColor.Enum g = runb.getUnderlineThemeColor();
                    int h = runb.getCharacterSpacing();
                    String iv = runb.getLang();
                    int j = 10;
                    int kv = 0;
                    int l = runb.getTextScale();
                    VerticalAlign m = runb.getSubscript();
                    String runTextQ2 = runb.toString();//前2
                    String news = runTextQ2 + text + runText;
                    if (StringUtils.isNotEmpty(runText) && StringUtils.isEmpty(runs.get(i - 2).toString()) && StringUtils.isEmpty(runs.get(i - 1).toString())) {
                        para.removeRun(i);
                        XWPFRun newRun = para.insertNewRun(i);
                        styleTo(newRun, runText.replace("#", ""), size, fam, bold, color, und, un, enums, cha, la, k, t, tx, sb);
                    }
                    if (StringUtils.isNotEmpty(news) && news.contains(re)) {

                        if (re.contains("fireChangeInfo") || re.contains("secPolluteHotPointNum")) {
                            para.removeRun(i - 2);
                            XWPFRun newRun = para.insertNewRun(i - 2);
                            styleTo(newRun, (news.replace("#", "")).replace(re, "{{" + re + "}}"), a, b, c, d, e, f, g, h, iv, j, kv, l, m);
                            para.removeRun(i);
                            para.insertNewRun(i).setText("");
                            para.removeRun(i - 1);
                            para.insertNewRun(i - 1).setText("");
                        }
                    }
                }
                if (runText.equals(re)) {
                    para.removeRun(i);
                    XWPFRun newRun = para.insertNewRun(i);
                    styleTo(newRun, re, size, fam, bold, color, und, un, enums, cha, la, k, t, tx, sb);
                }

                if (StringUtils.isNotEmpty(text) && re.equals((text + runText).replace("#", "")) && text.equals(re) && runText.equals("#")) {
                    para.removeRun(i);
                    XWPFRun newRun = para.insertNewRun(i);
                    styleTo(newRun, "", size, fam, bold, color, und, un, enums, cha, la, k, t, tx, sb);
                } else if (StringUtils.isNotEmpty(text) && re.equals((text + runText).replace("#", "")) && !text.equals(re)) {
                    para.removeRun(i - 1);
                    XWPFRun newRun = para.insertNewRun(i - 1);
                    styleTo(newRun, !runText.contains("@") && runText.contains("Png") || !runText.contains("@") && runText.contains("Pic") ? "{{@" : "{{", size, fam, bold, color, und, un, enums, cha, la, k, t, tx, sb);
                    para.removeRun(i);
                    XWPFRun newRuns = para.insertNewRun(i);
                    styleTo(newRuns, (text + runText).replace("#", "") + "}}", size, fam, bold, color, und, un, enums, cha, la, k, t, tx, sb);
                } else if (text.contains("#") && runText.equals(re) && !text.equals("#")) {
                    para.removeRun(i - 1);
                    XWPFRun newRuns = para.insertNewRun(i - 1);
                    styleTo(newRuns, (text).replace("#", "{{"), sizea, fama, bolda, colora, unda, una, enumsa, chaa, laa, ka, ta, txa, sba);
                } else if (runText.equals(re) || runText.equals(re + "#")) {
                    para.removeRun(i);
                    XWPFRun newRun = para.insertNewRun(i);
                    styleTo(newRun, !runText.contains("@") && runText.contains("Png") || !runText.contains("@") && runText.contains("Pic") ? "@" + re + "}}"
                            : re + "}}", size, fam, bold, color, und, un, enums, cha, la, k, t, tx, sb);
                } else if (runText.equals("#" + re)) {
                    para.removeRun(i);
                    XWPFRun newRun = para.insertNewRun(i);
                    styleTo(newRun, !runText.contains("@") && runText.contains("Png") || !runText.contains("@") && runText.contains("Pic") ? "{{@" + re
                            : "{{" + re, size, fam, bold, color, und, un, enums, cha, la, k, t, tx, sb);
                } else if (runText.equals("#" + re + "#")) {
                    para.removeRun(i);
                    XWPFRun newRun = para.insertNewRun(i);
                    styleTo(newRun, !runText.contains("@") && runText.contains("Png") || !runText.contains("@") && runText.contains("Pic") ?
                            "{{@" + re + "}}" : "{{" + re + "}}", size, fam, bold, color, und, un, enums, cha, la, k, t, tx, sb);
                } else if (runText.contains(re)) {
                    if (runText.contains(re + "#")) {
                        para.removeRun(i);
                        XWPFRun newRun = para.insertNewRun(i);
                        styleTo(newRun, runText.replace(re + "#", re + "}}"), size, fam, bold, color, und, un, enums, cha, la, k, t, tx, sb);
                        if (text.equals("#")) {
                            para.removeRun(i - 1);
                            XWPFRun newRuns = para.insertNewRun(i - 1);
                            styleTo(newRuns, "{{", sizea, fama, bolda, colora, unda, una, enumsa, chaa, laa, ka, ta, txa, sba);
                        }
                    }
                    if (runText.contains("#" + re)) {
                        para.removeRun(i);
                        XWPFRun newRun = para.insertNewRun(i);
                        styleTo(newRun, runText.replace("#" + re, !runText.contains("@") && runText.contains("Png") || !runText.contains("@") && runText.contains("Pic") ? "{{@" + re
                                : "{{" + re), size, fam, bold, color, und, un, enums, cha, la, k, t, tx, sb);
                    }
                    if (runText.contains("#" + re + "#")) {
                        para.removeRun(i);
                        XWPFRun newRun = para.insertNewRun(i);
                        styleTo(newRun, runText.replace("#" + re + "#", runText.contains("Png") || runText.contains("Pic") ?
                                "{{@" + re + "}}" : "{{" + re + "}}"), size, fam, bold, color, und, un, enums, cha, la, k, t, tx, sb);
                    }
                } else if (!runText.contains(re) && runText.contains("#")) {
                    int num1 = 0;
                    for (int i2 = 0; i2 < runText.length(); i2++) {
                        //英文字符g对应的是103（分大小写），下面有查看某个字符代表的具体数字的方法
                        //查看有几个‘g’出现在这个字符串
                        if (runText.codePointAt(i2) == '#') {
                            num1++;
                        }
                    }
                    String patterns = "[\u4e00-\u9fa5]";
                    Pattern r = Pattern.compile(patterns);
                    int count = 0;
                    if (num1 == 2) {
                        String news = runText.replace("#", "");
                        Matcher m = r.matcher(news);

                        while (m.find()) {
                            count++;
                        }
                        if (count == news.replace(" ", "").length()) {
                            para.removeRun(i);
                            XWPFRun newRun = para.insertNewRun(i);
                            styleTo(newRun, news, size, fam, bold, color, und, un, enums, cha, la, k, t, tx, sb);

                        }
                    }
                    //如果上级是re
                    if (re.equals(text) && !runText.equals("#") && runText.contains("#") && count == 0) {
                        para.removeRun(i);
                        XWPFRun newRuns = para.insertNewRun(i);
                        styleTo(newRuns, (runText).replace("#", "}}"), size, fam, bold, color, und, un, enums, cha, la, k, t, tx, sb);

                    }
                }
                text = runText;
            }
        }
        for (int i = 0; i < runs.size(); i++) {
            XWPFRun run = runs.get(i);
            //获取格式
            String runText = run.toString(), fam = run.getFontFamily(), color = run.getColor(), und = run.getUnderlineColor(), la = run.getLang(), pic = run.getPictureText();
            int size = run.getFontSize(), cha = run.getCharacterSpacing(), k = run.getKerning(), t = run.getTextPosition(), tx = run.getTextScale();
            boolean bold = run.isBold();
            UnderlinePatterns un = run.getUnderline();
            STThemeColor.Enum enums = run.getUnderlineThemeColor();
            VerticalAlign sb = (run.getSubscript());
            if (andIncrement == 0) {
                fam = "方正小标宋简体";
                tx = 90;
                para.removeRun(i);
                XWPFRun newRun = para.insertNewRun(i);
                styleTo(newRun, runText, size, fam, bold, color, und, un, enums, cha, la, k, t, tx, sb);
            }

        }
        System.err.println("|结束替换 =\t" + para.getParagraphText());
    }

    private static XWPFRun styleTo(XWPFRun newRun, String news, int size, String fam, boolean bold, String color, String und, UnderlinePatterns un, STThemeColor.Enum enums, int cha, String la, int k, int t, int tx, VerticalAlign sb) {
        newRun.setText(news);
        newRun.setCharacterSpacing(cha);
        newRun.setFontSize(size);
        newRun.setFontFamily(fam);
        newRun.setBold(bold);
        newRun.setColor(color);
        newRun.setUnderlineColor(und);
        newRun.setUnderline(un);
        newRun.setUnderlineThemeColor(String.valueOf(enums));
        newRun.setTextScale(tx);
        newRun.setKerning(k);
        newRun.setLang(la);
        newRun.setTextPosition(t);
        newRun.setSubscript(sb);
        return newRun;
    }

    public static void replaceInPara(String filePath, String templath) throws IOException {
        InputStream iss = Files.newInputStream(Paths.get(filePath));
        XWPFDocument doc = new XWPFDocument(iss);
        AtomicInteger n = new AtomicInteger();

        InputStream ist = Files.newInputStream(Paths.get(templath));
        XWPFDocument doct = new XWPFDocument(ist);
        System.out.println("|==========================|>模板通配符开始替换<|=======================================\n\t");

        replaceInParaTem(doc, doct);

        OutputStream ost = Files.newOutputStream(Paths.get(templath));
        doct.write(ost);
        ost.close();
        ist.close();

        OutputStream oss = Files.newOutputStream(Paths.get(filePath));
        doc.write(oss);
        oss.close();
        iss.close();
        System.out.println("|==========================|>模板通配符结束替换<|=======================================\n\t");
    }

    private static void replaceInParaTem(XWPFDocument doc, XWPFDocument doct) {
        doc.getParagraphs().stream().filter(Objects::nonNull).forEach(v -> {
            try {
                doct.getParagraphs().stream().filter(Objects::nonNull).forEach(c -> {
                    List<XWPFRun> runv = v.getRuns();
                    List<XWPFRun> runc = c.getRuns();
                    for (int i = 0; i < runc.size(); i++) {
                        XWPFRun rc = runc.get(i);
                        String runText = rc.toString(), fam = rc.getFontFamily(), color = rc.getColor(), und = rc.getUnderlineColor(), la = rc.getLang(), pic = rc.getPictureText();
                        int size = rc.getFontSize(), cha = rc.getCharacterSpacing(), k = rc.getKerning(), t = rc.getTextPosition(), tx = rc.getTextScale();
                        boolean bold = rc.isBold();
                        UnderlinePatterns un = rc.getUnderline();
                        STThemeColor.Enum enums = rc.getUnderlineThemeColor();
                        VerticalAlign sb = (rc.getSubscript());
                        for (int iv = 0; iv < runv.size(); iv++) {
                            XWPFRun rv = runv.get(iv);
                            if (rc.toString().replace("#", "").equals(rv.toString())) {

                                v.removeRun(iv);
                                XWPFRun newRun = v.insertNewRun(iv);
                                styleTo(newRun, rv.toString(), size, fam, bold, color, und, un, enums, cha, la, k, t, tx, sb);
                            }
                        }
                    }

                });
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });
    }

    /**
     * 合并runs中的内容
     *
     * @param para
     * @return
     */
    private static List<XWPFRun> replaceText(XWPFParagraph para) {
        List<XWPFRun> runs = para.getRuns();
        String str = "";
        boolean flag = false;
        for (int i = 0; i < runs.size(); i++) {
            XWPFRun run = runs.get(i);
            String runText = run.toString();

            if (flag || runText.equals("#")) {

                str = str + runText;
                flag = true;
                para.removeRun(i);
                if (runText.equals("#")) {
                    flag = false;
                    para.insertNewRun(i).setText(str);
                    str = "";
                }
                i--;
            }

        }

        return runs;
    }

    /**
     * 替换表格里面的变量
     *
     * @param doc    要替换的文档
     * @param params 参数
     */
    private static void replaceInTable(XWPFDocument doc, Map<String, Object> params) throws XmlException, IOException {
        Iterator<XWPFTable> iterator = doc.getTablesIterator();
        XWPFTable table;
        List<XWPFTableRow> rows;
        List<XWPFTableCell> cells;
        List<XWPFParagraph> paras;
        while (iterator.hasNext()) {
            table = iterator.next();
            rows = table.getRows();

        }
    }

    /**
     * 关闭输入流
     *
     * @param is
     */
    private void close(InputStream is) {
        if (is != null) {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 关闭输出流
     *
     * @param os
     */
    private void close(OutputStream os) {
        if (os != null) {
            try {
                os.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}